/*
 *  base_list.c
 *  mongoose
 *
 *  Created by xl on 11-5-2.
 *  Copyright 2011 Justin Lee. All rights reserved.
 *
 */

#include "base_list.h"
#include <stdlib.h>

#define base_malloc malloc
#define base_memset memset
#define base_free free

#ifdef inline
#define base_inline inline
#else
#define base_inline
#endif

static base_inline BASE_LIST* create_node()
{
	BASE_LIST* p = base_malloc(sizeof(BASE_LIST));
	if (p)
	{
		base_memset(p, 0, sizeof(BASE_LIST));
	}
	return p;
}

static base_inline void delete_node(BASE_LIST* p)
{
	if (p)
	{
		base_free(p);
	}
}

BASE_LIST* base_list_create()
{
	return create_node();
}

void base_list_append(BASE_LIST *list, BASE_LIST_CONTENT content)
{
	if (list)
	{
		if (list->next == NULL && list->content == NULL)
		{
			list->content = content;
			return;
		}
		
		while (list->next != NULL) 
		{
			list = list->next;
		}
		
		list->next = create_node();
		list = list->next;
		list->content = content;
	}
}

void base_list_remove(BASE_LIST *list, BASE_LIST_CONTENT content)
{
	BASE_LIST *pre_list = NULL;
	
	if (list)
	{
		while (list != NULL && list->content != content)
		{
			pre_list = list;
			list = list->next;
		}
		
		if (list)
		{
			if (pre_list == NULL)
			{
				//first node, we copy the next to it, and prepare to delete the next one.
				pre_list = list;
				list = list->next;
                if (list)
                {
                    pre_list->content = list->content;
                }
			}
			
			//non-first node, just delete it.
            if (list)
            {
                pre_list->next = list->next;
            }
            else
            {
                //first node :(
                list = pre_list;
            }
			
			delete_node(list);
		}	
	}
}

void base_list_destory(BASE_LIST* list, BASE_LIST_REMOVE_NODE node_remove_handler, void* param)
{
	BASE_LIST *pre_list = NULL;

	while (list)
	{
		pre_list = list;
		list = list->next;
		if (node_remove_handler)
		{
			node_remove_handler(pre_list->content, param);
		}
		delete_node(pre_list);
	}
}

BASE_LIST_CONTENT base_list_conditon_find(BASE_LIST *list, BASE_LIST_COMPARE_FUNC compare, void* param)
{
	BASE_LIST_CONTENT c = NULL;
	if (compare)
	{
		while (list != NULL)
		{
			if (compare(list->content, param))
			{
				c = list->content;
				break;
			}
			list = list->next;
		}
	}
	return c;
}
